package dog.weatherwallpaper.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Time {
	public static final int MILLIS_IN_AN_HOUR = 3600000;

	private final String INPUT_DATE_FORMAT = "yyyy-MM-dd";
	private final String OUTPUT_DATE_FORMAT = "E";
	private final String OUTPUT_FULL_DATE_FORMAT = "EEEE d";
	private final String INPUT_TIME_FORMAT = "hh:mm aa";
	private final String OUTPUT_TIME_FORMAT = "H:mm";

	private final TimeZone UTC = TimeZone.getTimeZone("UTC");

	/**
	 * Changes date to the output format, either full form (Monday 16) or short form (Mon)
	 * Returns unchanged string if it cannot be parsed.
	 */
	public String formatDate(final String date, final boolean full) {
		if (date == null || date.length() != INPUT_DATE_FORMAT.length()) { return date; }

		try {
			Date d = new SimpleDateFormat(INPUT_DATE_FORMAT).parse(date);
			return new SimpleDateFormat(full ? OUTPUT_FULL_DATE_FORMAT : OUTPUT_DATE_FORMAT).format(d);
		} catch (ParseException e) {
			App.sendMail(e);
			return date;
		}
	}

	/**
	 * Changes time to the output format (0-23). <br>
	 * Returns unchanged string if it cannot be parsed.
	 */
	public String formatTime(final String time) {
		if (time == null || time.length() != INPUT_TIME_FORMAT.length()) { return time; }

		DateFormat input = new SimpleDateFormat(INPUT_TIME_FORMAT, Locale.ENGLISH);
		input.setTimeZone(UTC);
		DateFormat output = new SimpleDateFormat(OUTPUT_TIME_FORMAT);
		output.setTimeZone(TimeZone.getDefault());

		try {
			Date t = input.parse(time);
			return output.format(t);
		} catch (ParseException e) {
			App.sendMail(e);
			return time;
		}
	}

	/**
	 * Converts <b>date</b> and <b>time</b> into a Date.
	 * Returns null if any of the strings cannot be parsed.
	 */
	public Date formatDateTime(final String date, final String time) {
		if (date == null || date.length() != INPUT_DATE_FORMAT.length() || time == null
				|| time.length() != INPUT_TIME_FORMAT.length()) { return null; }

		DateFormat dateFormat = new SimpleDateFormat(INPUT_DATE_FORMAT);
		DateFormat timeFormat = new SimpleDateFormat(INPUT_TIME_FORMAT, Locale.ENGLISH);
		timeFormat.setTimeZone(UTC);

		Calendar d, t;
		try {
			d = getCalendar(dateFormat.parse(date));
			t = getCalendar(timeFormat.parse(time));
		} catch (ParseException e) {
			App.sendMail(e);
			return null;
		}

		d.set(Calendar.HOUR_OF_DAY, t.get(Calendar.HOUR_OF_DAY));
		d.set(Calendar.MINUTE, t.get(Calendar.MINUTE));
		d.set(Calendar.SECOND, t.get(Calendar.SECOND));

		return d.getTime();
	}

	private Calendar getCalendar(final Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal;
	}

	/**
	 * Returns current date in this format: yyyy-MM-dd
	 */
	public String today() {
		return new SimpleDateFormat(INPUT_DATE_FORMAT).format(new Date());
	}

	/**
	 * Checks if <b>date</b> is older than <b>hours</b>. Returns
	 * true if <b>date</b> is null or it is a future date.
	 */
	public boolean isOlderThan(final Date date, final int hours) {
		if (date == null) { return true; }
		long period = new Date().getTime() - date.getTime();
		if (period < 0) { return true; }
		return period > hours * MILLIS_IN_AN_HOUR;
	}
}